package com.bdv.md.service.impl;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bdv.md.dao.TransactionDao;
import com.bdv.md.dao.TransHistoryDao;
import com.bdv.md.en.ConstantValues;
import com.bdv.md.model.MapTbl;
import com.bdv.md.model.Transaction;
import com.bdv.md.model.TransHistory;
import com.bdv.md.service.TransactionService;

@Service("txService")
@Transactional(readOnly = false)
public class TransactionServiceImpl implements TransactionService {

	private static final String ALPHANUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrtuvwxyz";
	protected static Random rnd = new Random();
	
	protected String randomAlphaNumeric( int idLength ) 
	{
	   StringBuilder sb = new StringBuilder( idLength );
	   for( int i = 0; i < idLength; i++ ) 
	      sb.append( ALPHANUM.charAt( rnd.nextInt(ALPHANUM.length()) ) );
	   return sb.toString();
	}

	@Autowired
	private TransactionDao transactionDao;
	@Autowired
	private TransHistoryDao transactionHistoryDao;
	
	public String validTxId(int len) {
		String randomAN = randomAlphaNumeric(len); 
		boolean valid = transactionDao.validateTxId(randomAN);
		return valid ? randomAN : validTxId(len) ;
	}
	public String validTxIdWithS(int len){
		return randomS(validTxId(len));
	}

	public Transaction saveNewTransaction(String txId, Integer mapId, String meterId, Integer type) {
		Transaction tx = new Transaction();
		MapTbl meter = new MapTbl();
		meter.setMapId(mapId);
		
		tx.setMeter(meter);
		tx.setTxId(txId);
		tx.setType(type);
		tx.setRetry(0);
		tx.setStatus("-1");
		tx.setRequestTime(new Timestamp(new Date().getTime()));
		transactionDao.saveOrUpdate(tx);
		
		TransHistory txHist = new TransHistory();
		txHist.setTxId(txId);
		String histType="";
		if(type== Integer.parseInt(ConstantValues.CC_AMR.getPLNCode())){
			histType = "AMR.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_TOKEN_REQUEST.getPLNCode())){
			histType = "TOK.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_LIM_KREDIT.getPLNCode())){
			histType = "LIM.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_ALERT.getPLNCode())){
			histType = "ALR.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_HISTORY_TOKEN.getPLNCode())){
			histType = "HIS.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_BILLING_HISTORY.getPLNCode())){
			histType = "BIL.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_AMR_PP.getPLNCode())){
			histType = "AMP.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_LOAD_PROFILE_PP.getPLNCode())){
			histType = "LOP.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_EVENT_LOG_PP.getPLNCode())){
			histType = "EVP.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_BILLING_PP.getPLNCode())){
			histType = "BIP.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_ALARM_PP.getPLNCode())){
			histType = "ALP.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_RECALL_LOAD_PROFILE_PP.getPLNCode())){
			histType = "REP.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_TIME_SYNC_PP.getPLNCode())){
			histType = "SYP.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_REMOTE_PP.getPLNCode())){
			histType = "RMP.PLN.0";
		}else if(type == Integer.parseInt(ConstantValues.CC_SCADA_SYSTEM_PP.getPLNCode())){
			histType = "SCP.PLN.0";
		}
		
		
		txHist.setType(histType);
		txHist.setRequestTime(tx.getRequestTime());
		txHist.setMeterId(meterId);
		transactionHistoryDao.saveOrUpdate(txHist);
		
		System.out.println("Save transaction.. map id: "+mapId+" Type: "+type);
		return tx;
	}
	public Transaction saveRetTransaction(String txId, Integer networkStatus) {
		Transaction oldTx = transactionDao.findById(txId);
		oldTx.setRetry(oldTx.getRetry()+1);
		oldTx.setStatus(networkStatus.toString());
		transactionDao.saveOrUpdate(oldTx);
		
		TransHistory oldTxHist = transactionHistoryDao.getTransHistoryByTxID(txId);
		TransHistory newTxHist = new TransHistory();
		Integer type = oldTx.getType();
		String histType="";
		if(type== Integer.parseInt(ConstantValues.CC_AMR.getPLNCode())){
			histType = "AMR.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_TOKEN_REQUEST.getPLNCode())){
			histType = "TOK.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_LIM_KREDIT.getPLNCode())){
			histType = "LIM.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_ALERT.getPLNCode())){
			histType = "ALR.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_HISTORY_TOKEN.getPLNCode())){
			histType = "HIS.PLN."+oldTx.getRetry();;
		}else if(type == Integer.parseInt(ConstantValues.CC_BILLING_HISTORY.getPLNCode())){
			histType = "BIL.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_AMR_PP.getPLNCode())){
			histType = "AMP.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_LOAD_PROFILE_PP.getPLNCode())){
			histType = "LOP.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_EVENT_LOG_PP.getPLNCode())){
			histType = "EVP.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_BILLING_PP.getPLNCode())){
			histType = "BIP.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_ALARM_PP.getPLNCode())){
			histType = "ALP.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_RECALL_LOAD_PROFILE_PP.getPLNCode())){
			histType = "REP.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_TIME_SYNC_PP.getPLNCode())){
			histType = "SYP.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_REMOTE_PP.getPLNCode())){
			histType = "RMP.PLN."+oldTx.getRetry();
		}else if(type == Integer.parseInt(ConstantValues.CC_SCADA_SYSTEM_PP.getPLNCode())){
			histType = "SCP.PLN."+oldTx.getRetry();
		}

		//newTxHist.setTxId(txId);
		newTxHist.setType(histType);
		newTxHist.setRequestTime(new Timestamp(new Date().getTime()));
		newTxHist.setNetworkStatus("RETRY."+networkStatus);
		newTxHist.setMeterId(oldTxHist.getMeterId());
		newTxHist.setRetryTxHis(oldTxHist);
		transactionHistoryDao.saveOrUpdate(newTxHist);
		
		return oldTx;
	}
	
	public void updateTransactionSuccessFailStatus(String txId, Integer networkStatus){
		Transaction oldTx = transactionDao.findById(txId);
		TransHistory oldTxHist = transactionHistoryDao.getTransHistoryByTxID(txId);
		oldTx.setStatus(networkStatus.toString());
		oldTxHist.setNetworkStatus(networkStatus == 0 ? "SUCCESS" :"FAIL TRANSACTION");
		
		transactionDao.saveOrUpdate(oldTx);
		transactionHistoryDao.saveOrUpdate(oldTxHist);
		
	}
	
	
	public void updateTransactionResponse(String txId){
		Transaction tx = transactionDao.findById(txId);
		tx.setResponseTime(new Timestamp(new Date().getTime()));
		transactionDao.saveOrUpdate(tx);
		
		TransHistory txh = transactionHistoryDao.getTransHistoryByTxID(txId);
		txh.setResponseTime(tx.getResponseTime());
		transactionHistoryDao.saveOrUpdate(txh);
	}
	public Transaction getTransactionByTrxId(String txId){
		return transactionDao.findById(txId);
	}

	private static String randomS(String trxId){
		int sPos = rnd.nextInt(5);
		if(sPos == 0) return "s"+trxId;
		if(sPos == 5) return trxId+"s";
		
		String fTrxId = trxId.substring(0, sPos);
		String lTrxId = trxId.substring(sPos);
		return fTrxId+"s"+lTrxId;
	}

}
